﻿//  Copyright (c) 2010 Ray Liang (http://www.dotnetage.com)
//  Dual licensed under the MIT and GPL licenses:
//  http://www.opensource.org/licenses/mit-license.php
//  http://www.gnu.org/licenses/gpl.html

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using DNA.Mvc.jQuery;
using System.Linq.Expressions;
using System.Collections;

namespace DNA.Mvc
{
    public static class DJMEExtensions
    {
        public static DnaControlFactory Dna(this AjaxHelper helper)
        {
            return new DnaControlFactory(helper.ViewContext,helper.ViewDataContainer);
        }

        public static DnaControlFactory<TModel> DnaFor<TModel>(this AjaxHelper<TModel> helper)
        {
            return new DnaControlFactory<TModel>(helper.ViewContext,helper.ViewDataContainer);
        }
    }

    public class DnaControlFactory<TModel>
    {
        private AjaxHelper<TModel> _ajaxHelper;

        private AjaxHelper<TModel> Ajax
        {
            get
            {
                if (_ajaxHelper == null)
                    _ajaxHelper = new AjaxHelper<TModel>(this.ViewContext, this.ViewDataContainer);
                return _ajaxHelper;
            }
        }

        public IViewDataContainer ViewDataContainer { get; private set; }

        public ViewContext ViewContext { get; private set; }

        public DnaControlFactory(ViewContext viewContext, IViewDataContainer viewDataContainer)
        {
            this.ViewDataContainer = viewDataContainer;
            this.ViewContext = viewContext;
        }

        public TextBoxBuilder Number<TValue>(Expression<Func<TModel, TValue>> expression)
        {
            return this.TextBox<TValue>(expression).NumericOnly();
        }

        public TextBoxBuilder TextBox<TValue>(Expression<Func<TModel, TValue>> expression)
        {
            ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, new ViewDataDictionary<TModel>());
            var builder = new TextBoxBuilder(new TextBox() { }, this.ViewContext,this.ViewDataContainer);

            if (modelMetadata.IsReadOnly)
                builder.Options(opts => { opts.ReadOnly = true; });

            if (!string.IsNullOrEmpty(modelMetadata.Watermark))
                builder.Watermark(modelMetadata.Watermark);

            if (this.ViewContext.ViewData.Model != null)
            {
                var value = expression.Compile().Invoke((TModel)this.ViewContext.ViewData.Model);
                if (modelMetadata.ModelType.Equals(typeof(int)))
                    builder.Value(value != null ? int.Parse(value.ToString()) : 0);
                else
                    builder.Value(value != null ? value.ToString() : "");
            }
            var html = new HtmlHelper<TModel>(this.ViewContext, this.ViewDataContainer);
            var ctrlName=modelMetadata.ContainerType.Name + "." + modelMetadata.PropertyName;

            builder.Name(ctrlName).HtmlAttributes(html.GetUnobtrusiveValidationAttributes(modelMetadata.PropertyName,modelMetadata));

            return builder;
        }

        public TextAreaBuilder TextArea<TValue>(Expression<Func<TModel, TValue>> expression)
        {
            ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, new ViewDataDictionary<TModel>());
            var builder = new TextAreaBuilder(new TextArea() { }, this.ViewContext, this.ViewDataContainer);

            if (modelMetadata.IsReadOnly)
                builder.ReadOnly();

            if (this.ViewContext.ViewData.Model != null)
                builder.Value(expression.Compile().Invoke((TModel)this.ViewContext.ViewData.Model) as string);
            var html = new HtmlHelper<TModel>(ViewContext, ViewDataContainer);
            builder.Name(modelMetadata.ContainerType.Name + "." + modelMetadata.PropertyName).HtmlAttributes(html.GetUnobtrusiveValidationAttributes(modelMetadata.PropertyName, modelMetadata));

            return builder;
        }

        public ListBoxBuilder<TModel> ListBox<TModel>(IEnumerable<TModel> model)
            where TModel : class
        {
            return new ListBoxBuilder<TModel>(new ListBox<TModel>(), this.ViewContext,this.ViewDataContainer).Bind(model);
        }

        public ComboBoxBuilder<TModel> ComboBox<TModel>(IEnumerable<TModel> model)
    where TModel : class
        {
            return new ComboBoxBuilder<TModel>(new ComboBox<TModel>(), this.ViewContext, this.ViewDataContainer).Bind(model);
        }

        public ComboBoxBuilder<TModel> ComboBox<TModel>(IEnumerable<TModel> model, Expression<Func<TModel, dynamic>> textFieldSelector,
            Expression<Func<TModel, dynamic>> valueFieldSelector)
where TModel : class
        {
            return new ComboBoxBuilder<TModel>(new ComboBox<TModel>(), this.ViewContext, this.ViewDataContainer).Bind(model,textFieldSelector,valueFieldSelector);
        }

        public SliderBuilder Slider<TValue>(Expression<Func<TModel, TValue>> expression)
        {
            ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, new ViewDataDictionary<TModel>());
            var builder = new SliderBuilder(new Slider() { }, this.ViewContext, this.ViewDataContainer);
            if (this.ViewContext.ViewData.Model != null)
            {
                int val = 0;
                var dvalue = expression.Compile().Invoke((TModel)this.ViewContext.ViewData.Model);
                if (dvalue != null)
                    int.TryParse(dvalue.ToString(), out val);
                builder.Value(val);
            }

            builder.Name(modelMetadata.ContainerType.Name + "." + modelMetadata.PropertyName);

            return builder;
        }

        public ButtonBuilder CheckBox<TValue>(Expression<Func<TModel, TValue>> expression, string imageUrl, string checkedImageUrl)
        {
            return this.CheckBox(expression, null, imageUrl, checkedImageUrl);
        }

        public ButtonBuilder CheckBox<TValue>(Expression<Func<TModel, TValue>> expression, string text, string imageUrl, string checkedImageUrl)
        {
            ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, new ViewDataDictionary<TModel>());
            var builder = new ButtonBuilder(new Button() { }, this.ViewContext, this.ViewDataContainer);
            bool value = false;
            string title = string.IsNullOrEmpty(text) ? modelMetadata.DisplayName : text;

            if (this.ViewContext.ViewData.Model != null)
            {
                var strValue = expression.Compile().Invoke((TModel)this.ViewContext.ViewData.Model);

                if (strValue != null)
                    bool.TryParse(strValue.ToString(), out value);
            }

            builder.Name(modelMetadata.ContainerType.Name + "." + modelMetadata.PropertyName);

            builder.ChangeType(ButtonTypes.LinkButton)
                  .Text(title)
                  .States(states =>
                  {
                      states.Add(title)
                          .ImageIcons(imageUrl)
                          .SetValue(true)
                          .Select(value);

                      states.Add(title)
                          .ImageIcons(checkedImageUrl)
                          .SetValue(false)
                          .Select(!value);
                  });
            return builder;
        }
    }

    public class DnaControlFactory
    {
        private AjaxHelper _ajaxHelper;

        private AjaxHelper Ajax
        {
            get 
            {
                if (_ajaxHelper == null)
                    _ajaxHelper = new AjaxHelper(this.ViewContext, this.ViewDataContainer);
                return _ajaxHelper; 
            }
        }

        public IViewDataContainer ViewDataContainer { get; private set; }

        public ViewContext ViewContext { get; private set; }

        public DnaControlFactory(ViewContext viewContext,IViewDataContainer viewDataContainer)
        {
            this.ViewDataContainer = viewDataContainer;
            this.ViewContext = viewContext;
        }

        public TabsBuilder Tabs() { return this.Tabs(""); }

        public TabsBuilder Tabs(string name)
        {
            return new TabsBuilder(new Tabs() { Name = name }, this.ViewContext,this.ViewDataContainer).GenerateId();
        }

        public MenuBuilder Menu() { return this.Menu(""); }

        public MenuBuilder Menu(string name)
        {
            return new MenuBuilder(new Menu() { Name = name }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        public TreeViewBuilder TreeView() { return this.TreeView(""); }

        public TreeViewBuilder TreeView(string name)
        {
            return new TreeViewBuilder(new TreeView() { Name = name }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        public TextBoxBuilder TextBox(string name)
        {
            return new TextBoxBuilder(new TextBox() { Name = name }, this.ViewContext, this.ViewDataContainer);
        }

        public TextBoxBuilder Password(string name)
        {
            return (new TextBoxBuilder(new TextBox() { Name = name }, this.ViewContext, this.ViewDataContainer)).Password();
        }

        public TextBoxBuilder Number(string name, int value)
        {
            return this.TextBox(name).Value(value).NumericOnly();
        }

        public ComboBoxBuilder ComboBox() { return this.ComboBox(null); }

        public ComboBoxBuilder  ComboBox(string name)
        {
            return new ComboBoxBuilder(new ComboBox<INavigable>() { Name = name }, this.ViewContext, this.ViewDataContainer).GenerateId() as ComboBoxBuilder;
        }

        public DialogBuilder Dialog(string title)
        {
            return Dialog(title, "");
        }

        public DialogBuilder Dialog(string title, string opener)
        {
            return Dialog("", title, opener);
        }

        public DialogBuilder Dialog(string name, string title, string opener)
        {
            return new DialogBuilder(new Dialog() { Name = name, Title = title, TriggerID = opener }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        public AccordionBuilder Accordion() { return this.Accordion(""); }

        public AccordionBuilder Accordion(string name)
        {
            return new AccordionBuilder(new Accordion() { Name = name }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        public SliderBuilder Slider() { return this.Slider(null); }

        public SliderBuilder Slider(string name)
        {
            return new SliderBuilder(new Slider() { Name = name }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        public SiteMapBuilder SiteMap() { return this.SiteMap(""); }

        public SiteMapBuilder SiteMap(string name)
        {
            return new SiteMapBuilder(new SiteMap() { Name = name }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        public DatePickerBuilder DatePicker(string name)
        {
            return new DatePickerBuilder(new DatePicker() { Name = name }, this.ViewContext, this.ViewDataContainer);
        }

        public ColorPickerBuilder ColorPicker(string name)
        {
            return new ColorPickerBuilder(new ColorPicker() { Name = name }, this.ViewContext, this.ViewDataContainer);
        }

        public ToolTipBuilder ToolTip()
        {
            return ToolTip("body");
        }

        public ToolTipBuilder ToolTip(string name)
        {
            return new ToolTipBuilder(new ToolTip() { Name = name }, this.ViewContext, this.ViewDataContainer);
        }

        public ListBoxBuilder ListBox(string name)
        {
            return new ListBoxBuilder(new ListBox<INavigable>() { Name = name }, this.ViewContext, this.ViewDataContainer);
        }

        public CollapsablePanelBuilder CollapsablePanel()
        {
            return this.CollapsablePanel("");
        }

        public CollapsablePanelBuilder CollapsablePanel(string name)
        {
            return new CollapsablePanelBuilder(new CollapsablePanel() { Name = name }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        public ButtonBuilder Checkbox(string name, string title, bool value)
        {
            return Button(name)
                .ChangeType(ButtonTypes.CheckBox)
                .Text(title)
                .Options(opts => opts.Value = value);

        }

        public ButtonBuilder Checkbox(string name, string title, bool value, string imgUrl, string checkedImageUrl)
        {
            return Button(name)
                .ChangeType(ButtonTypes.LinkButton)
                                  .Text(title)
                                  .States(states =>
                                  {
                                      states.Add(title)
                                          .ImageIcons(imgUrl)
                                          .SetValue(true)
                                          .Select(value);

                                      states.Add(title)
                                          .ImageIcons(checkedImageUrl)
                                          .SetValue(false)
                                          .Select(!value);
                                  });
        }

        public ButtonBuilder Button() { return this.Button(""); }

        public ButtonBuilder Button(string name)
        {
            return new ButtonBuilder(new Button() { Name = name }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        public ButtonBuilder Link(string url)
        {
            return this.Link(null, url, null);
        }

        public ButtonBuilder Link(string text, string url)
        {
            return this.Link(text, url, null);
        }

        public ButtonBuilder Link(string text, string url, string iconUrl)
        {
            var btn = this.Button().ChangeType(ButtonTypes.LinkButton).Text(text).NavigateUrl(url);
            if (!string.IsNullOrEmpty(iconUrl))
                btn.ImageIcons(iconUrl);
            return btn;
        }

        public ToolbarBuilder Toolbar()
        {
            return this.Toolbar("");
        }

        public ToolbarBuilder Toolbar(string name)
        {
            return new ToolbarBuilder(new Toolbar() { Name = name }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        public RichTextBoxBuilder RichTextBox(string name)
        {
            return new RichTextBoxBuilder(new RichTextBox() { Name = name }, this.ViewContext, this.ViewDataContainer);
        }

        public GridBuilder<TModel> Grid<TModel>(IEnumerable model)
    where TModel : class
        {
            return new GridBuilder<TModel>(new Grid() { Model = model }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        public GridBuilder<TModel> Grid<TModel>(IEnumerable<TModel> model)
            where TModel : class
        {
            return new GridBuilder<TModel>(new Grid() { Model = model }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        public GridBuilder<TModel> Grid<TModel>()
            where TModel : class
        {
            return new GridBuilder<TModel>(new Grid() { }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        public PagerBuilder Pager() { return this.Pager(""); }

        public PagerBuilder Pager(string name)
        {
            return new PagerBuilder(new Pager() { Name = name }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        public SplitterBuilder Splitter() { return this.Splitter(null); }

        public SplitterBuilder Splitter(string name)
        {
            return new SplitterBuilder(new Splitter() { Name = name }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }

        //public TextAreaBuilder TextArea<TModel, TValue>(Expression<Func<TModel, TValue>> expression)
        //{
        //    ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression<TModel, TValue>(expression, new ViewDataDictionary<TModel>());

        //    ModelState state;
        //    string attemptedValue;
        //    string fullHtmlFieldName = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(ExpressionHelper.GetExpressionText((LambdaExpression)expression));
        //    if (string.IsNullOrEmpty(fullHtmlFieldName))
        //        throw new ArgumentException("name");
        //    var area=this.TextArea(fullHtmlFieldName);

        //    if (helper.ViewData.ModelState.TryGetValue(fullHtmlFieldName, out state) && (state.Errors.Count > 0))
        //        area.HtmlAttributes(new { @class = HtmlHelper.ValidationInputCssClassName });

        //    if ((state != null) && (state.Value != null))
        //        attemptedValue = state.Value.AttemptedValue;
        //    else if (modelMetadata.Model != null)
        //    {
        //        attemptedValue = modelMetadata.Model.ToString();
        //    }
        //    else
        //    {
        //        attemptedValue = string.Empty;
        //    }
        //    area.Value(Environment.NewLine + attemptedValue);
        //    return area;
        //}

        public TextAreaBuilder TextArea() { return this.TextArea(null); }

        public TextAreaBuilder TextArea(string name)
        {
            return new TextAreaBuilder(new TextArea() { Name = name }, this.ViewContext, this.ViewDataContainer).GenerateId();
        }
    }
}
